#include "VideoCapture.h"
#include <stdio.h>
#include "NalParser.h"
#include "htime.h"

extern "C" {
#include "libavutil/avutil.h"
#include "libavformat/avformat.h"
}

VideoCapture::VideoCapture(std::string streamUrl)
{
    m_streamUrl = streamUrl;
    m_demux = std::make_shared<XDemux>();
    m_HFFDecodeThread = std::make_shared<HFFDecodeThread>();
    setSleepPolicy(NO_SLEEP, 0);
}


VideoCapture::~VideoCapture()
{
}


bool VideoCapture::doPrepare()
{
  bool ret =  m_demux->Open(m_streamUrl.c_str());
  if (!ret) {
    return false;
  }
  AVCodecParameters* para = m_demux->CopyVPara();
  if (para == NULL) {
    return false;
  }
  m_HFFDecodeThread->SetPara(para);
  //m_HFFDecodeThread->Open();
  m_HFFDecodeThread->start();
  std::this_thread::sleep_for(std::chrono::milliseconds(2));
  return true;
}


void VideoCapture::doTask()
{
  AVPacket *pkt = m_demux->Read();
  if (!pkt) {
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
    return ;
  }

  //判断数据是视频
  if (!m_demux->IsAudio(pkt)){
    //uint8_t *data = (pkt->data) + 45;
    uint8_t *data = (pkt->data) + 4;
    int frame_type = h264_frame_type(data, pkt->size);
    // for ( int i = 0; i < 50; i++) {
    //   printf("%X ", data[i]);
    // }
    // printf("\n");
    std::string frame_type_str;
    std::vector<int8_t> payload;
    char sei_time[14] = {0};
    switch (frame_type){
      case 0x01:
        frame_type_str = "I Frame";
        break;
      case 0x02:
        frame_type_str = "P Frame";
        break; 
      case 0x03:
        frame_type_str = "SPS Frame";
        break;
      case 0x04:
        frame_type_str = "PPS Frame";
        break;
      case 0x05:
        frame_type_str = "SEI Frame";
        GetSEIPayload ("H264", (pkt->data) + 4, 37, payload);
        // for (int i = 0; i < payload.size(); i++) {
        //   printf("i = %d, p = %c\n", i, payload[i]);
        // }
        memcpy(sei_time, payload.data()+16, 13);
        break;
      case 0x06:
        frame_type_str = "VPS Frame";
        break;
      case 0x07:
        frame_type_str = "Other Frame";
        break;
      default:
        frame_type_str = "Other Frame";
        break;
    }

    unsigned long long recv_time =  gethrtime_us() / 1000;
    
    // datetime_t dt =  datetime_now();
    // char time_str[1024] = {0};
    // sprintf(time_str, "%04d-%02d-%02d %02d:%02d:%02d %03d",dt.year, dt.month, dt.day,dt.hour, dt.min, dt.sec, dt.ms);
    // printf("recv frame: time = %ld, type = %s, size=%d\n", recv_time, frame_type_str.c_str(), pkt->size);
    // printf("sei_time =         %s\n", sei_time);

    printf("file:%s function:%s line:%d time2 = %lld\n", __FILE__, __FUNCTION__, __LINE__, gethrtime_us() / 1000);
    printf("recv frame: time = %lld, type = %s, size=%d\n", recv_time, frame_type_str.c_str(), pkt->size);
    printf("file:%s function:%s line:%d sei_time = %lld\n", __FILE__, __FUNCTION__, __LINE__, atoll(sei_time));
    printf("##recv time:%lld\n", recv_time);
    printf("##sei_time :%lld\n", atoll(sei_time));


    UserData* user_data = (UserData*)malloc(sizeof(UserData));
    user_data->id = pkt->pts;
    user_data->sei_time = atoll(sei_time);
    user_data->recv_frame_time = recv_time;

    m_HFFDecodeThread->Push(pkt, user_data);
    //printf("file:%s function:%s line:%d time2 = %lld\n", __FILE__, __FUNCTION__, __LINE__, gethrtime_us() / 1000);

  }
    
  std::this_thread::sleep_for(std::chrono::milliseconds(1));
  
  //av_packet_free(&pkt);
}


bool VideoCapture::doFinish()
{
    m_demux->Close();

    return true;
}
